package main.java.com.amanda.suafa;

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

import java.util.Scanner;

/**
 * @author amanda
 * @Description 算法5.1 低位优先的字符串排序
 */

public class LSD {
    public static void sort(String[] a, int W) {
        // 通过前w个字符将a[]排序
        int N = a.length;
        int R = 256;
        String[] aux = new String[N];

        for (int d = W-1; d >= 0; d--) {
            // 根据第d个字符用键索引计数法排序
            // 1.计算出现频率
            int[] count = new int[R+1];
            for (int i = 0; i < N; i++) {
                count[a[i].charAt(d) + 1]++;
            }
            // 2.将频率转换为索引
            for (int r = 0; r < R; r++) {
                count[r+1] += count[r];
            }
            // 3.将元素分类
            for (int i = 0; i < N; i++) {
                aux[count[a[i].charAt(d)]++] = a[i];
            }
            // 4.回写
            for (int i = 0; i < N; i++) {
                a[i] = aux[i];
            }
        }
    }

    /**
     * 按升序重新排列32位整数数组。
     * 这比Arrays.sort()快2-3倍。
     * @param a the array to be sorted
     */
    private static final int BITS_PER_BYTE = 8;
    public static void sort(int[] a) {
        final int BITS = 32;                 // each int is 32 bits
        final int R = 1 << BITS_PER_BYTE;    // each bytes is between 0 and 255
        final int MASK = R - 1;              // 0xFF
        final int w = BITS / BITS_PER_BYTE;  // each int is 4 bytes

        int n = a.length;
        int[] aux = new int[n];

        for (int d = 0; d < w; d++) {

            // compute frequency counts
            int[] count = new int[R+1];
            for (int i = 0; i < n; i++) {
                int c = (a[i] >> BITS_PER_BYTE*d) & MASK;
                count[c + 1]++;
            }

            // compute cumulates
            for (int r = 0; r < R; r++)
                count[r+1] += count[r];

            // for most significant byte, 0x80-0xFF comes before 0x00-0x7F
            if (d == w-1) {
                int shift1 = count[R] - count[R/2];
                int shift2 = count[R/2];
                for (int r = 0; r < R/2; r++)
                    count[r] += shift1;
                for (int r = R/2; r < R; r++)
                    count[r] -= shift2;
            }

            // move data
            for (int i = 0; i < n; i++) {
                int c = (a[i] >> BITS_PER_BYTE*d) & MASK;
                aux[count[c]++] = a[i];
            }

            // copy back
            for (int i = 0; i < n; i++)
                a[i] = aux[i];
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        String[] a = str.split(" ");
        int n = a.length;
        int w = a[0].length();
        for (int i = 0; i < n; i++)
            assert a[i].length() == w : "Strings must have fixed length";
        sort(a, w);
        for (int i = 0; i < n; i++)
            StdOut.println(a[i]);
    }
}
/*
4GPC938 2IYE230 3CI0720 1ICK750 10HV845 4JZY524 1ICK750 3CI0720 10HV845 10HV845 2RLA629 2RLA629 3ATW723
 */